package com.nanbei.dp;

import java.util.Arrays;

/**
 * @ClassDescription: 零钱问题（动态规划） leetcode 518
 * @JdkVersion: 1.8
 * @Author: libs
 * @Created: 2024/7/8 13:51
 */
public class CoinChangeIi {

//给你一个整数数组 coins 表示不同面额的硬币，另给一个整数 amount 表示总金额。
//
// 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额，返回 0 。
//
// 假设每一种面额的硬币有无限个。
//
// 题目数据保证结果符合 32 位带符号整数。
//
//
//
//
//
//
// 示例 1：
//
//
//输入：amount = 5, coins = [1, 2, 5]
//输出：4
//解释：有四种方式可以凑成总金额：
//5=5
//5=2+2+1
//5=2+1+1+1
//5=1+1+1+1+1
//
//
// 示例 2：
//
//
//输入：amount = 3, coins = [2]
//输出：0
//解释：只用面额 2 的硬币不能凑成总金额 3 。
//
//
// 示例 3：
//
//
//输入：amount = 10, coins = [10]
//输出：1
//
//
//
//
// 提示：
//
//
// 1 <= coins.length <= 300
// 1 <= coins[i] <= 5000
// coins 中的所有值 互不相同
// 0 <= amount <= 5000
//
//
    /*
     面值    0        1        2        3        4        5
       1    1        1        1        1        1        1
       2    1        1        2        2        3        3
       5    1        1        2        2        3        4


     面值    0        1        2        3
            1        0        0        0
       2    1        0        1        0

     */

    public int change(int amount, int[] coins) {
        int[][] dp = new int[coins.length][amount + 1];
        // 初始化  当硬币的面额正好为当前要凑齐的金额时也算是一种情况
        for (int i = 0; i < coins.length; i++) {
            dp[i][0] = 1;
        }

        for (int j = 1; j < amount+1; j++) {
            if (j >= coins[0]){
                dp[0][j] =  dp[0][j-coins[0]];
            }
        }
        System.out.println(Arrays.deepToString(dp));

        // 计算的情况数为 上一次凑齐的计算结果加上 当前金额减去硬币面额的结果数
        for (int i = 1; i < coins.length; i++) {
            for (int j = 1; j < amount+1; j++) {
                if (j >= coins[i]){
                    dp[i][j] =  dp[i][j-coins[i]] + dp[i-1][j];
                }else {
                    dp[i][j] =  dp[i-1][j];
                }
            }
            System.out.println(Arrays.deepToString(dp));
        }


        return dp[coins.length-1][amount];

    }


    public int change2(int amount, int[] coins) {
        int[] dp = new int[amount + 1];
        // 初始化
        dp[0] = 1;

        System.out.println(Arrays.toString(dp));

        for (int coin : coins) {
            for (int j = coin; j < amount + 1; j++) {

                dp[j] = dp[j - coin] + dp[j];

            }
            System.out.println(Arrays.toString(dp));
        }


        return dp[amount];

    }

}
